%%%----------------------------------------------------------------------
%%% File    : mod_http_bind.erl
%%% Author  : Stefan Strigler <steve@zeank.in-berlin.de>
%%% Purpose : Implementation of XMPP over BOSH (XEP-0206)
%%% Created : Tue Feb 20 13:15:52 CET 2007
%%%
%%%
%%% ejabberd, Copyright (C) 2002-2016   ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License along
%%% with this program; if not, write to the Free Software Foundation, Inc.,
%%% 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
%%%
%%%----------------------------------------------------------------------

%%%----------------------------------------------------------------------
%%% This module acts as a bridge to ejabberd_http_bind which implements
%%% the real stuff, this is to handle the new pluggable architecture for
%%% extending ejabberd's http service.
%%%----------------------------------------------------------------------

-module(mod_http_bind).

-author('steve@zeank.in-berlin.de').

%%-define(ejabberd_debug, true).

-behaviour(gen_mod).

-export([start/2, stop/1, process/2, mod_opt_type/1, depends/2]).

-include("ejabberd.hrl").
-include("logger.hrl").

-include("jlib.hrl").

-include("ejabberd_http.hrl").

-include("http_bind.hrl").

-define(PROCNAME_MHB, ejabberd_mod_http_bind).

%% Duplicated from ejabberd_http_bind.
%% TODO: move to hrl file.
-record(http_bind,
	{id, pid, to, hold, wait, process_delay, version}).

%%%----------------------------------------------------------------------
%%% API
%%%----------------------------------------------------------------------

process([], #request{method = 'POST', data = <<>>}) ->
    ?DEBUG("Bad Request: no data", []),
    {400, ?HEADER,
     #xmlel{name = <<"h1">>, children = [{xmlcdata, <<"400 Bad Request">>}]}};
process([],
	#request{method = 'POST', data = Data, ip = IP, opts = Opts}) ->
    ?DEBUG("Incoming data: ~s", [Data]),
    ejabberd_http_bind:process_request(Data, IP, Opts);
process([], #request{method = 'GET', data = <<>>}) ->
    {200, ?HEADER, get_human_html_xmlel()};
process([], #request{method = 'OPTIONS', data = <<>>}) ->
    {200, ?OPTIONS_HEADER, <<>>};
process([], #request{method = 'HEAD'}) ->
    {200, ?HEADER, <<>>};
process(_Path, _Request) ->
    ?DEBUG("Bad Request: ~p", [_Request]),
    {400, ?HEADER,
     #xmlel{name = <<"h1">>, children = [{xmlcdata, <<"400 Bad Request">>}]}}.

%%%----------------------------------------------------------------------
%%% BEHAVIOUR CALLBACKS
%%%----------------------------------------------------------------------
start(_Host, _Opts) ->
    setup_database().

stop(_Host) ->
    ok.

setup_database() ->
    migrate_database(),
    mnesia:create_table(http_bind,
			[{ram_copies, [node()]},
			 {attributes, record_info(fields, http_bind)}]).

migrate_database() ->
    case catch mnesia:table_info(http_bind, attributes) of
        [id, pid, to, hold, wait, process_delay, version] ->
	    ok;
        _ ->
	    %% Since the stored information is not important, instead
	    %% of actually migrating data, let's just destroy the table
	    mnesia:delete_table(http_bind)
    end.

mod_opt_type(max_inactivity) ->
    fun (I) when is_integer(I), I > 0 -> I end;
mod_opt_type(max_pause) ->
    fun (I) when is_integer(I), I > 0 -> I end;
mod_opt_type(_) -> [max_inactivity, max_pause].

depends(_Host, _Opts) ->
    [].

%%%----------------------------------------------------------------------
%%% Help Web Page
%%%----------------------------------------------------------------------

get_human_html_xmlel() ->
    Heading = <<"ejabberd ",
		(iolist_to_binary(atom_to_list(?MODULE)))/binary>>,
    #xmlel{name = <<"html">>,
	   attrs =
	       [{<<"xmlns">>, <<"http://www.w3.org/1999/xhtml">>}],
	   children =
	       [#xmlel{name = <<"head">>,
		       children =
			   [#xmlel{name = <<"title">>,
				   children = [{xmlcdata, Heading}]},
			    #xmlel{name = <<"style">>,
				   children = [{xmlcdata, get_style_cdata()}]}]},
		#xmlel{name = <<"body">>,
		       children =
			   [#xmlel{name = <<"div">>,
				   attrs = [{<<"class">>, <<"container">>}],
				   children = get_container_children(Heading)}]}]}.

get_container_children(Heading) ->
    [#xmlel{name = <<"div">>,
	    attrs = [{<<"class">>, <<"section">>}],
	    children =
		[#xmlel{name = <<"div">>,
			attrs = [{<<"class">>, <<"block">>}],
			children =
			    [#xmlel{name = <<"a">>,
				    attrs = [{<<"href">>, <<"https://www.ejabberd.im">>}],
				    children =
					[#xmlel{name = <<"img">>,
						attrs = [{<<"height">>, <<"32">>},
							 {<<"src">>, get_image_src()}]}]}]}]},
     #xmlel{name = <<"div">>,
	    attrs = [{<<"class">>, <<"white section">>}],
	    children =
		[#xmlel{name = <<"div">>,
			attrs = [{<<"class">>, <<"block">>}],
			children =
			    [#xmlel{name = <<"h1">>, children = [{xmlcdata, Heading}]},
			     #xmlel{name = <<"p">>, children =
					[{xmlcdata, <<"An implementation of ">>},
					 #xmlel{name = <<"a">>,
						attrs = [{<<"href">>, <<"http://xmpp.org/extensions/xep-0206.html">>}],
						children = [{xmlcdata, <<"XMPP over BOSH (XEP-0206)">>}]}]},
			     #xmlel{name = <<"p">>, children =
					[{xmlcdata, <<"This web page is only informative. To "
						      "use HTTP-Bind you need a Jabber/XMPP "
						      "client that supports it.">>}]}]}]},
     #xmlel{name = <<"div">>,
	    attrs = [{<<"class">>, <<"section">>}],
	    children =
		[#xmlel{name = <<"div">>,
			attrs = [{<<"class">>, <<"block">>}],
			children =
			    [#xmlel{name = <<"a">>,
				    attrs = [{<<"href">>, <<"https://www.ejabberd.im">>},
					     {<<"title">>, <<"ejabberd XMPP server">>}],
				    children = [{xmlcdata, <<"ejabberd">>}]},
			     {xmlcdata, <<" is maintained by ">>},
			     #xmlel{name = <<"a">>,
				    attrs = [{<<"href">>, <<"https://www.process-one.net">>},
					     {<<"title">>, <<"ProcessOne - Leader in Instant Messaging and Push Solutions">>}],
				    children = [{xmlcdata, <<"ProcessOne">>}]} ]}]}
    ].

get_style_cdata() ->
    <<"
      body {
        margin: 0;
        padding: 0;
        font-family: sans-serif;
        color: #fff;
      }
      h1 {
        font-size: 3em;
        color: #444;
      }
      p {
        line-height: 1.5em;
        color: #888;
      }
      a {
        color: #fff;
      }
      a:hover,
      a:active {
        text-decoration: underline;
      }
      .container {
        position: absolute;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        background: #424A55;
        background-image: -webkit-linear-gradient(270deg, rgba(48,52,62,0) 24%, #30353e 100%);
        background-image: linear-gradient(-180deg, rgba(48,52,62,0) 24%, #30353e 100%);
      }
      .section {
        padding: 3em;
      }
      .white.section {
        background: #fff;
        border-bottom: 4px solid #41AFCA;
      }
      .white.section a {
        text-decoration: none;
        color: #41AFCA;
      }
      .white.section a:hover,
      .white.section a:active {
         text-decoration: underline;
      }
      .block {
        margin: 0 auto;
        max-width: 900px;
        width: 100%;
      }">>.

get_image_src() ->
    <<"">>.
